﻿using Basic.FormModel;
using Basic.FormModel.FormViewCol;
using Basic.FormModel.QueryColumn;
using Basic.FormRemoteModel;
using Basic.FormRemoteModel.PageLayout.Model;
using Basic.FormRemoteModel.QueryForm.Model;
using Basic.FormRemoteModel.QueryInter.Model;
using Basic.UserFormService.Model;
using Basic.UserFormService.PageControl.Calculate;
using SqlSugar;
using WeDonekRpc.Helper;
using WeDonekRpc.SqlSugar;
using WeDonekRpc.SqlSugar.VirtualQuery;

namespace Basic.UserFormService
{
    internal static class LinqHelper
    {
        public static IWhereCol[] Merge ( this IWhereCol[] cols, IWhereCol[] other )
        {
            if ( cols.IsNull() )
            {
                return other;
            }
            List<IWhereCol> list = new List<IWhereCol>(cols);
            other.ForEach(a =>
            {
                if ( a is WhereCollect i )
                {
                    list.Add(a);
                    return;
                }
                WhereCol t = (WhereCol)a;
                WhereCol? col = cols.Find<IWhereCol, WhereCol?>(c =>
                {
                    if ( c is WhereCol k )
                    {
                        return k.Name == t.Name && k.Func == t.Func;
                    }
                    return false;
                }, c => (WhereCol)c);
                if ( col == null )
                {
                    list.Add(a);
                }
                else
                {
                    WhereCol val = col.Value;
                    val.Value = t.Value;
                }
            });
            return list.ToArray();
        }
        public static IWhereCol[] GetWhere ( this SearchParam[] where, Dictionary<long, ColTable> cols )
        {
            return where.ConvertAll<SearchParam, IWhereCol>(c =>
            {
                if ( c.ColId.Length == 1 )
                {
                    ColTable col = cols[c.ColId[0]];
                    return new WhereCol
                    {
                        ConditionalType = c.Mode.GetConditionalType(),
                        DbType = col.DataType.GetDbType(),
                        Func = c.Mode == QueryFilterMode.Between ? FuncType.Between : FuncType.None,
                        IsAnd = true,
                        Table = col.Table,
                        Name = col.Name,
                        Value = c.Vals.IsNull() ? c.Val : c.Vals
                    };
                }
                return new WhereCollect
                {
                    Collect = c.ColId.ConvertAll(a =>
                    {
                        ColTable col = cols[a];
                        return new WhereCol
                        {
                            ConditionalType = c.Mode.GetConditionalType(),
                            DbType = col.DataType.GetDbType(),
                            Func = c.Mode == QueryFilterMode.Between ? FuncType.Between : FuncType.None,
                            IsAnd = false,
                            Table = col.Table,
                            Name = col.Name,
                            Value = c.Vals.IsNull() ? c.Val : c.Vals
                        };
                    })
                };

            });
        }
        public static IWhereCol[] GetWhere ( this PageFilterParam[] where, Dictionary<long, ColTable> cols, long companyId, Dictionary<string, string> extend )
        {
            ColTable comId = cols.Where(c => c.Value.Name == ConstDic.CompanyIdColName).Select(c => c.Value).FirstOrDefault();
            if ( comId == null && where.IsNull() )
            {
                return null;
            }
            else if ( where.IsNull() )
            {
                return new IWhereCol[]
                {
                    new WhereCol
                    {
                        ConditionalType =  SqlSugar.ConditionalType.Equal,
                        DbType =  System.Data.DbType.Int64,
                        Func = FuncType.None,
                        IsAnd = true,
                        Name = ConstDic.CompanyIdColName,
                        Value =  companyId,
                        Table= comId.Table
                    }
                };
            }
            IWhereCol[] list = where.ConvertAll<PageFilterParam, IWhereCol>(c =>
            {
                if ( c.Children.IsNull() )
                {
                    ColTable col = cols[c.ColId.Value];
                    return new WhereCol
                    {
                        ConditionalType = c.Mode.Value.GetConditionalType(),
                        DbType = col.DataType.GetDbType(),
                        Func = c.Mode.Value == PageFilterMode.Between ? FuncType.Between : FuncType.None,
                        IsAnd = c.IsAnd,
                        Table = col.Table,
                        Name = col.Name,
                        Value = c.Value.GetFilterValue(extend)
                    };
                }
                WhereCollect collect = new WhereCollect
                {
                    Collect = c.Children.ConvertAll(a =>
                    {
                        ColTable col = cols[a.ColId.Value];
                        return new WhereCol
                        {
                            ConditionalType = a.Mode.Value.GetConditionalType(),
                            DbType = col.DataType.GetDbType(),
                            Func = a.Mode.Value == PageFilterMode.Between ? FuncType.Between : FuncType.None,
                            IsAnd = a.IsAnd,
                            Table = col.Table,
                            Name = col.Name,
                            Value = a.Value.GetFilterValue(extend)
                        };
                    })
                };
                collect.Collect[0].IsAnd = c.IsAnd;
                return collect;
            });
            if ( comId == null )
            {
                return list;
            }
            return list.TopInsert(new WhereCol
            {
                ConditionalType = SqlSugar.ConditionalType.Equal,
                DbType = System.Data.DbType.Int64,
                Func = FuncType.None,
                IsAnd = true,
                Name = ConstDic.CompanyIdColName,
                Value = companyId,
                Table = comId.Table
            });
        }
        public static object GetFilterValue ( this PageFilterItemVal[] value, Dictionary<string, string> extend )
        {
            if ( value.IsNull() )
            {
                return null;
            }
            else if ( value.Length == 1 )
            {
                return _GetValue(value[0], extend);
            }
            return value.ConvertAll(a => _GetValue(a, extend));
        }
        public static object _GetValue ( PageFilterItemVal value, Dictionary<string, string> extend )
        {
            if ( value == null )
            {
                return null;
            }
            else if ( value.ValueType == FilterValueType.函数 )
            {
                return CalculateValue.Calculate(value.Val);
            }
            else if ( value.ValueType == FilterValueType.环境参数 )
            {
                return extend.GetValueOrDefault(value.Val);
            }
            else
            {
                return value.ValueType == FilterValueType.固定值 ? value.Val : value.Vals;
            }
        }
        public static object GetFilterValue ( this PageFilterItemVal[] value )
        {
            if ( value.IsNull() )
            {
                return null;
            }
            else if ( value.Length == 1 )
            {
                return _GetValue(value[0]);
            }
            return value.ConvertAll(_GetValue);
        }
        private static object _GetValue ( PageFilterItemVal value )
        {
            if ( value == null )
            {
                return null;
            }
            else if ( value.ValueType == FilterValueType.函数 )
            {
                return CalculateValue.Calculate(value.Val);
            }
            else
            {
                return value.ValueType == FilterValueType.固定值 ? value.Val : value.Vals;
            }
        }
        public static QueryFuncType GetQueryFuncType ( this PageFuncType type, out string format, out DateType? dateType )
        {
            format = null;
            dateType = null;
            switch ( type )
            {
                case PageFuncType.最小值:
                    return QueryFuncType.Min;
                case PageFuncType.计数:
                    return QueryFuncType.Count;
                case PageFuncType.去重计数:
                    return QueryFuncType.DistinctCount;
                case PageFuncType.取和:
                    return QueryFuncType.Sum;
                case PageFuncType.最大值:
                    return QueryFuncType.Max;
                case PageFuncType.取年月:
                    format = "yyyyMM";
                    return QueryFuncType.DateTimeFormat;
                case PageFuncType.取年份:
                    format = "yyyy";
                    return QueryFuncType.DateTimeFormat;
                case PageFuncType.取月份:
                    format = "MM";
                    return QueryFuncType.DateTimeFormat;
                case PageFuncType.取周几:
                    dateType = DateType.Weekday;
                    return QueryFuncType.DateValue;
                case PageFuncType.取季度:
                    dateType = DateType.Quarter;
                    return QueryFuncType.DateValue;
                case PageFuncType.取年的第几天:
                    return QueryFuncType.WeekOfYear;
                default:
                    return QueryFuncType.None;
            }
        }
        public static System.Data.DbType GetDbType ( this PhyTableDataType type )
        {
            switch ( type )
            {
                case PhyTableDataType.Number:
                    return System.Data.DbType.Decimal;
                case PhyTableDataType.Short:
                    return System.Data.DbType.Int16;
                case PhyTableDataType.Int:
                    return System.Data.DbType.Int32;
                case PhyTableDataType.Long:
                    return System.Data.DbType.Int64;
                case PhyTableDataType.Array:
                    return System.Data.DbType.String;
                case PhyTableDataType.Date:
                    return System.Data.DbType.Date;
                case PhyTableDataType.DateTime:
                    return System.Data.DbType.DateTime;
                case PhyTableDataType.Bool:
                    return System.Data.DbType.Boolean;
                default:
                    return System.Data.DbType.String;
            }
        }
        public static ConditionalType GetConditionalType ( this QueryFilterMode mode )
        {
            if ( mode == QueryFilterMode.等于 )
            {
                return ConditionalType.Equal;
            }
            else if ( mode == QueryFilterMode.大于等于 )
            {
                return ConditionalType.GreaterThanOrEqual;
            }
            else if ( mode == QueryFilterMode.大于 )
            {
                return ConditionalType.GreaterThan;
            }
            else if ( mode == QueryFilterMode.小于 )
            {
                return ConditionalType.LessThan;
            }
            else if ( mode == QueryFilterMode.小于等于 )
            {
                return ConditionalType.LessThanOrEqual;
            }
            else if ( mode == QueryFilterMode.EndsWith )
            {
                return ConditionalType.LikeRight;
            }
            else if ( mode == QueryFilterMode.StartsWith )
            {
                return ConditionalType.LikeLeft;
            }
            else if ( mode == QueryFilterMode.Link )
            {
                return ConditionalType.Like;
            }
            return ConditionalType.Equal;
        }
        public static ConditionalType GetConditionalType ( this PageFilterMode mode )
        {
            if ( mode == PageFilterMode.等于 )
            {
                return ConditionalType.Equal;
            }
            else if ( mode == PageFilterMode.大于等于 )
            {
                return ConditionalType.GreaterThanOrEqual;
            }
            else if ( mode == PageFilterMode.大于 )
            {
                return ConditionalType.GreaterThan;
            }
            else if ( mode == PageFilterMode.小于 )
            {
                return ConditionalType.LessThan;
            }
            else if ( mode == PageFilterMode.小于等于 )
            {
                return ConditionalType.LessThanOrEqual;
            }
            else if ( mode == PageFilterMode.EndsWith )
            {
                return ConditionalType.LikeRight;
            }
            else if ( mode == PageFilterMode.StartsWith )
            {
                return ConditionalType.LikeLeft;
            }
            else if ( mode == PageFilterMode.Link )
            {
                return ConditionalType.Like;
            }
            else if ( mode == PageFilterMode.In )
            {
                return ConditionalType.In;
            }
            else if ( mode == PageFilterMode.NotIn )
            {
                return ConditionalType.NotIn;
            }
            else if ( mode == PageFilterMode.不等于 )
            {
                return ConditionalType.NoEqual;
            }
            else if ( mode == PageFilterMode.NoLink )
            {
                return ConditionalType.NoLike;
            }
            return ConditionalType.Equal;
        }
        public static DataFuncType ToDataFuncType ( this FormColumnFuncType type )
        {
            switch ( type )
            {
                case FormColumnFuncType.字典项:
                    return DataFuncType.字典项;
                case FormColumnFuncType.树形字典:
                    return DataFuncType.树形字典;
                case FormColumnFuncType.选项值:
                    return DataFuncType.选项值;
                case FormColumnFuncType.部门单位ID:
                    return DataFuncType.部门单位ID;
                case FormColumnFuncType.人员ID:
                    return DataFuncType.人员ID;
                case FormColumnFuncType.公司ID:
                    return DataFuncType.公司ID;
                case FormColumnFuncType.上传的附件:
                    return DataFuncType.上传的附件;
                default:
                    return DataFuncType.基本;
            }
        }
        public static string[] SplitDel ( this string str )
        {
            if ( str.IsNull() )
            {
                return null;
            }
            return str.Substring(1, str.Length - 2).Split('|');
        }
        public static object GetFormValue ( this FormListItem form, int index )
        {
            if ( form.DataType == FormRecordDataType.Bool )
            {
                return form.BoolVal[index];
            }
            else if ( form.DataType == FormRecordDataType.Date || form.DataType == FormRecordDataType.DateTime )
            {
                long? val = form.LongVal[index];
                return val.HasValue ? val.Value.ToDateTime() : null;
            }
            else if ( form.DataType == FormRecordDataType.Time || form.DataType == FormRecordDataType.Long )
            {
                return form.LongVal[index];
            }
            else if ( form.DataType == FormRecordDataType.Number )
            {
                return form.NumVal[index];
            }
            else if ( form.DataType == FormRecordDataType.Array )
            {
                string[] val = form.Vals[index];
                return val.IsNull() == false ? val.Join('|', '|') : null;
            }
            return form.StrVal[index];
        }
        public static object GetFormValue ( this FormVal form )
        {
            if ( form.DataType == FormRecordDataType.Bool )
            {
                return form.BoolVal;
            }
            else if ( form.DataType == FormRecordDataType.Date || form.DataType == FormRecordDataType.DateTime )
            {
                return form.LongVal.HasValue ? form.LongVal.Value.ToDateTime() : null;
            }
            else if ( form.DataType == FormRecordDataType.Time || form.DataType == FormRecordDataType.Long )
            {
                return form.LongVal;
            }
            else if ( form.DataType == FormRecordDataType.Number )
            {
                return form.NumVal;
            }
            else if ( form.DataType == FormRecordDataType.Array )
            {
                return form.Vals.IsNull() == false ? form.Vals.Join('|', '|') : null;
            }
            return form.StrVal;
        }
        public static FormRecordDataType ToRecordDataType ( this PhyTableDataType type )
        {
            switch ( type )
            {
                case PhyTableDataType.Varchar:
                    return FormRecordDataType.String;
                case PhyTableDataType.NVarchar:
                    return FormRecordDataType.String;
                case PhyTableDataType.Number:
                    return FormRecordDataType.Number;
                case PhyTableDataType.Int:
                    return FormRecordDataType.Long;
                case PhyTableDataType.Date:
                    return FormRecordDataType.Date;
                case PhyTableDataType.DateTime:
                    return FormRecordDataType.DateTime;
                case PhyTableDataType.Short:
                    return FormRecordDataType.Long;
                case PhyTableDataType.Array:
                    return FormRecordDataType.Array;
                case PhyTableDataType.Bool:
                    return FormRecordDataType.Bool;
                case PhyTableDataType.Long:
                    return FormRecordDataType.Long;
                default:
                    return FormRecordDataType.String;
            }
        }
        public static object CovertDefFormat ( this QueryCol col )
        {
            switch ( col.DataType )
            {
                case PhyTableDataType.Bool:
                    return col.DefValue == "true";
                case PhyTableDataType.Int:
                    return int.Parse(col.DefValue);
                case PhyTableDataType.DateTime:
                    return Tools.PaseDateTime(col.DefValue);
                case PhyTableDataType.Date:
                    return Tools.PaseDateTime(col.DefValue);
                case PhyTableDataType.Number:
                    return decimal.Parse(col.DefValue);
                case PhyTableDataType.Short:
                    return short.Parse(col.DefValue);
                case PhyTableDataType.Array:
                    return col.DefValue.Split(',');
                case PhyTableDataType.Long:
                    return long.Parse(col.DefValue);
                default:
                    return col.DefValue;
            }
        }
        public static FormRecordDataType GetDataType ( this QueryCol col )
        {
            if ( col.ColumnSet != null && col.ColumnSet.TryGetValue("Format", out object val) && val == "time" )
            {
                return FormRecordDataType.Time;
            }
            return col.DataType.ToRecordDataType();
        }
        public static FormRecordDataType GetDataType ( this FormViewColDto col )
        {
            if ( col.ColumnSet != null && col.ColumnSet.TryGetValue("Format", out object val) && val == "time" )
            {
                return FormRecordDataType.Time;
            }
            return col.DataType.ToRecordDataType();
        }
    }
}
